package com.ty.springbootshiro.config;


import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.ty.springbootshiro.entity.Right;
import com.ty.springbootshiro.service.RoleService;
import jakarta.annotation.Resource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;

import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * ShiroConfig
 *
 * @aurhor Administrator  whs
 * @since 2024/10/8
 */
@Configuration
public class ShiroConfig {

    @Resource
    private RoleService roleService;

    //注入redis参数 ，从 pom.xml 文件中获取
    @Value("${spring.data.redis.host}")
    private String host;
    @Value("${spring.data.redis.port}")
    private int port;
    @Value("${spring.data.redis.password}")
    private String password;
    @Value("${spring.data.redis.connect-timeout}")
    private int timeout;


    @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect() {  // thymeleaf 页面上使用 shiro 标签
        return new ShiroDialect();
    }


    /**
     * 开启Shiro注解
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    /**
     * 开启 aop 注解支持
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * 创建 redisManager
     * @return
     */
    @Bean
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
//        redisManager.setHost(host);
//      redisManager.setPort(port);
//      redisManager.setDatabase(port);

        redisManager.setHost(host + ":" + port); // #shiro-redis v3.3.1

        redisManager.setPassword(password);
        redisManager.setTimeout(timeout);
        return redisManager;
    }

    /**
     * 缓存管理器
     */
    @Bean
    public CacheManager shiroCacheManager() {
        RedisCacheManager cacheManager = new RedisCacheManager();
        cacheManager.setRedisManager(redisManager());
        // 缓存名称
        cacheManager.setPrincipalIdFieldName("usrName");
        // 缓存有效时间
        cacheManager.setExpire(1800);
        return cacheManager;
    }

    /**
     * 创建 RedisCacheManager 注入 RedisManager
     * @return
     */
    @Bean
    public RedisCacheManager cacheManager(){
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        // 缓存名称
        redisCacheManager.setPrincipalIdFieldName("usrName");
        // 缓存有效时间
        redisCacheManager.setExpire(timeout);
        return redisCacheManager;
    }

    /**
     * 会话操作
     * 创建 RedisSessionDAO 注入 RedisManager
     * @return
     */
    @Bean
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }

    /**
     * 会话管理
     * 创建 DefaultWebSessionManager 注入 RedisSessionDAO
     * @return
     */
    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO());
        return sessionManager;
    }

    /**
     * shiro 提供的 CredentialsMatcher 散列实现 HashedCredentialsMatcher 用于密码验证
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        // 使用 md5 算法进行加密
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        // 设置散列次数 ： 意为加密几次
        hashedCredentialsMatcher.setHashIterations(520);
        return hashedCredentialsMatcher;
    }



    @Bean
    public MyShiroRealm myShiroRealm() {   // 自定义Realm
        MyShiroRealm myShiroRealm = new MyShiroRealm();

        // 设置启用缓存，并设置缓存名称
        myShiroRealm.setCachingEnabled(true);
        myShiroRealm.setAuthenticationCachingEnabled(true);
        myShiroRealm.setAuthenticationCacheName("authenticationCache");

        // 设置凭证（密码）匹配器
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());

        return myShiroRealm;
    }

    @Bean
    public SecurityManager securityManager() {  // 安全管理器 SecurityManager
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //注入 Realm
        securityManager.setRealm(myShiroRealm());
        SecurityUtils.setSecurityManager(securityManager);


        // 注入缓存管理器
        securityManager.setCacheManager(cacheManager());
        // 注入会话管理器
        securityManager.setSessionManager(sessionManager());


        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { // 过滤器 权限验证
        ShiroFilterFactoryBean shiroFilterFactory = new ShiroFilterFactoryBean();
        // 注入securityManager
        shiroFilterFactory.setSecurityManager(securityManager);

        // 权限验证 ： 使用 Filter 控制资源（URL）的访问
        shiroFilterFactory.setLoginUrl("/index");
        shiroFilterFactory.setSuccessUrl("/main");
        shiroFilterFactory.setUnauthorizedUrl("/403"); //没有权限跳转到403
//
//        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>(); // 必须使用LinkedHashMap 有序集合
//
//        // 配置可以匿名访问资源的url： 静态资源
//        filterChainDefinitionMap.put("/css/**", "anon");
//        filterChainDefinitionMap.put("/fonts/**", "anon");
//        filterChainDefinitionMap.put("/images/**", "anon");
//        filterChainDefinitionMap.put("/js/**", "anon");
//        filterChainDefinitionMap.put("/localcss/**", "anon");
//        filterChainDefinitionMap.put("/localjs/**", "anon");
//
//        filterChainDefinitionMap.put("/login/**", "anon");
//        filterChainDefinitionMap.put("/logout/**", "anon");  // 注销过滤器 ， 自动注销
//
//        // 配置需要特定权限才能范文的资源的url
////        // 静态授权： 包括全部需要特定权限才能访问的资源URl
////        filterChainDefinitionMap.put("/user/list", "perms[用户列表]");
////        filterChainDefinitionMap.put("/user/save", "perms[用户添加]");
////        filterChainDefinitionMap.put("/user/edit", "perms[用户编辑]");
////        filterChainDefinitionMap.put("/user/del/", "perms[用户删除]");
//
//
//
////        // 动态授权
//        List<Right> rights = roleService.findAllRights();
//        for (Right right : rights) {
//            if (right.getRightUrl()!=null && right.getRightUrl().trim().equals("")) { // .startsWith("/user/")
//                filterChainDefinitionMap.put(right.getRightUrl(), "perms["+right.getRightUrl()+"]");
//            }
//        }
//
//
//        // 配置认证访问 ： 其他资源URl必须认证通过才能访问
//        filterChainDefinitionMap.put("/**", "authc");  // 必须放在过滤器链的最后面
//
//        shiroFilterFactory.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactory;
    }




}
